<?php


namespace App\Models\CacheModel;


use app\common\lib\exception\ApiException;
use App\Models\Api\BaseCache;
use think\Cache;
use think\Log;
use traits\model\SoftDelete;
use AstroTool\Cache\CacheManage;

class ZlPosterShareActive extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.zl_poster_share_active';
    protected $cacheModel = 'fortune.poster_share_active';

    protected $deleteTime = 'delete_time';

    use SoftDelete;

    /**
     * 更新海报信息
     * @param $id
     * @param $data
     * @param int $week
     * @return bool
     */
    public function updateData($id, $data, $week = 0)
    {
        try
        {
            $this->allowField(true)->save($data, ['id' => $id]);
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->setCache($data);
            if (isset($data['zan']))
            {   // 更新投票信息
                CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('ranking', $week)
                    ->listAdd([$id => $data['zan']], 0, 'ranking');
            }
            return true;
        }
        catch (\Exception $e)
        {
            Log::write("海报分享活动 海报信息更新失败：{$e->getMessage()};File:{$e->getFile()};Line:{$e->getLine()}", 'error', true);
            return false;
        }
    }

    /**
     * 参与海报评选
     */
    public function joinActive($data)
    {
        try
        {
            $day = $data['week'] . ':' . date('Ymd');

            $posterId = $this->insertGetId($data);
            // 添加投票列表数据
            $this->listDataAdd($data['week'], [$posterId => $data['create_time']]);
            // 添加排行榜数据
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('ranking', $data['week'])->listAdd([$posterId => 0], 0, 'ranking');
            // 添加 用户参与列表数据
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('user_join_record', $data['uid'])->listAdd([$posterId => $data['create_time']], 0, 'user_join_record');
            // 今日上传海报IDs
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('today', $day)->listAdd([$posterId => $data['create_time']], 0, 'today');

            $userNowWeekPosterIdCacheKey = "poster_active:poster_id:{$data['week']}:{$data['uid']}";
            Cache::set($userNowWeekPosterIdCacheKey, $posterId, 604800); // 7天 = 3600*24*7 = 604800
            return [
                'status' => true,
                'poster_id' => $posterId
            ];
        }
        catch (\Exception $e)
        {
            Log::write("海报分享活动 参加评选失败：{$e->getMessage()};File:{$e->getFile()};Line:{$e->getLine()}", 'error', true);
            return [
                'status' => false,
                'poster_id' => 0
            ];
        }
    }

    /**
     * 退出海报评选
     * @param $uid
     * @param $week
     * @param $id
     * @return bool
     */
    public function leaveActive($uid, $week, $id)
    {
        try
        {
            $day = $week . ':' . date('Ymd');

            // 软删除
            self::destroy($id);
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->rmCache();
            // 删除投票列表数据
            $this->listDataDel($week, [$id]);
            // 删除排行榜数据
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('ranking', $week)->delJudge([$id], 'ranking');
            // 删除 今日上传海报Ids
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('today', $day)->delJudge([$id], 'today');
            // 删除 用户参与列表数据
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('user_join_record', $uid)->delJudge([$id], 'user_join_record');

            $userNowWeekPosterIdCacheKey = "poster_active:poster_id:{$week}:{$uid}";
            Cache::rm($userNowWeekPosterIdCacheKey);
            return true;
        }
        catch (\Exception $e)
        {
            Log::write("海报分享活动 退出评选失败：{$e->getMessage()};File:{$e->getFile()};Line:{$e->getLine()}", 'error', true);
            return false;
        }
    }

    /**
     * 获取当前活动的周期
     */
    public function getActiveWeekNum(): int
    {
        $fortuneShareConfig = (new AppConfig())->configInfo('fortune_share');

        $weekStartTime = (int)$fortuneShareConfig['poster_share_active_week_start_time'];

        return ceil((time() - $weekStartTime) / 604800); // 7天 = 3600*24*7 = 604800
    }

    /**
     * 获取本周参与的海报ID
     * @param int $uid
     * @param int $week
     * @return int
     */
    public function getNowWeekPosterId(int $uid, int $week): int
    {
        $userNowWeekPosterIdCacheKey = "poster_active:poster_id:{$week}:{$uid}";
        $posterId = Cache::get($userNowWeekPosterIdCacheKey, false);

        if ($posterId === false)
        {
            $posterId = $this->where(['uid' => $uid, 'week' => $week])->order('id desc')->value('id');

            if (!$posterId)
            {
                $posterId = 0;
            }

            Cache::set($userNowWeekPosterIdCacheKey, $posterId, 604800); // 7天 = 3600*24*7 = 604800
        }

        return (int)$posterId;
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array|false|string
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            $this->alias('p');
            if ($ids)
            {
                $this->whereIn('p.id', $ids);
            } else
            {

            }

            return $this->join('wechat_backup_07_18_14_43_00.app_user u', 'u.id=p.uid')->column('p.*,u.nickname,u.avatar', 'p.id');
        }
        catch (\Exception $e)
        {
            return [];
        }
    }

    /**
     * 获取排行榜列表
     * @param int $week
     * @return array
     * @throws \Exception
     */
    public function getRankingList(int $week)
    {
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('ranking', $week)
            ->setPage(1)
            ->setPageSize(10)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($week)
            {
                try
                {
                    $data = $this->where(['week' => $week, 'status' => 1])->order('zan ' . $sortType)->column('zan', 'id');
                    $resData = [];
                    foreach ($data as $id => $zanNum)
                    {
                        $resData[$id] = ['zan' => $zanNum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'zan', 0, 'ranking');

        if ($rankingPageData['data'])
        {
            $rankingData = $this->batchGetInfoByIds(array_keys($rankingPageData['data']), ['id', 'poster', 'nickname', 'avatar', 'zan', 'status']);

            $resData = [];
            $delIds = [];
            foreach ($rankingPageData['data'] as $id => $zanNum)
            {
                if (isset($rankingData[$id]) && (int)$rankingData[$id]['status'] === 1)
                {   // 数据正常 则返回
                    // $zanStr = $rankingData[$id]['zan'] >= 1000 ? sprintf('%.1fk', $rankingData[$id]['zan'] / 1000) : $rankingData[$id]['zan'];

                    $resData[] = [
                        'id' => (int)$rankingData[$id]['id'],
                        'poster_url' => $rankingData[$id]['poster'],
                        'nickname' => $rankingData[$id]['nickname'],
                        'avatar' => $rankingData[$id]['avatar'],
                        'zan_num' => $rankingData[$id]['zan'],
                    ];
                } else
                {
                    $delIds[] = $id;
                }
            }

            if ($delIds)
            {   // 删除掉 某些状态异常的数据
                $cacheModel = CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('ranking', $week);
                foreach ($delIds as $id)
                {
                    $cacheModel->delJudge([$id], 'ranking');
                }
            }
            return $resData;
        } else
        {
            return [];
        }
    }

    /**
     * 获取用户排名信息
     * @param $week
     * @return array
     * @throws \Exception
     */
    public function getRankingIndex($week)
    {
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('ranking', $week)
            ->setPage(-1)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($week)
            {
                try
                {
                    $data = $this->where(['week' => $week, 'status' => 1])->order('zan ' . $sortType)->column('zan', 'id');
                    $resData = [];
                    foreach ($data as $id => $zanNum)
                    {
                        $resData[$id] = ['zan' => $zanNum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'zan', 0, 'ranking');

        $resData = [];
        $index = 1;
        foreach ($rankingPageData['data'] as $id => $zanNum)
        {
            $resData[$id] = [
                'ranking_index' => $index,
                'zan_num' => (int)$zanNum
            ];

            $index++;
        }

        return $resData;
    }

    /**
     * 投票/取消投票
     * @param $uid
     * @param $posterId
     * @return array
     */
    public function zanOrCancelZan($uid, $posterId)
    {
        $posterShareActiveZanRecordModel = new ZlPosterShareActiveZanRecord();
        // 获取用户所有投票的海报ID信息
        $posterIdsData = $posterShareActiveZanRecordModel->getZanPosterIds($uid);

        if (isset($posterIdsData[$posterId]))
        {   // 取消点赞
            $res = $posterShareActiveZanRecordModel->cancelZan($uid, $posterId);
            $resData = [
                'status' => $res,
                'zan' => -1,
                'msg' => $res ? '取消投票成功' : '服务异常，取消投票失败',
                'data' => ['status' => $res ? 0 : 1]
            ];
        } else
        {   // 点赞
            $res = $posterShareActiveZanRecordModel->zan($uid, $posterId);
            $resData = [
                'status' => $res,
                'zan' => 1,
                'msg' => $res ? '投票成功' : '服务异常，投票失败',
                'data' => ['status' => $res ? 1 : 0]
            ];
        }

        return $resData;
    }

    /**
     * 获取虚拟海报ids
     * @param $week
     * @return array
     * @throws \Exception
     */
    public function getVirtualPosterIds($week)
    {
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('virtual', $week)
            ->setPage(-1)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($week)
            {
                try
                {
                    $data = $this->where(['week' => $week, 'status' => 1, 'user_type' => 2])->column('zan', 'id');
                    $resData = [];
                    foreach ($data as $id => $zanNum)
                    {
                        $resData[$id] = ['zan' => $zanNum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'zan', 0, 'virtual');

        return $rankingPageData['data'] ? array_keys($rankingPageData['data']) : [];
    }

    /**
     * 获取今日上传海报ids
     * @param $week
     * @param $day
     * @return array
     * @throws \Exception
     */
    public function getTodayPosterIds($week, $day)
    {
        $cacheKeyId = $week . ':' . $day;
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('today', $cacheKeyId)
            ->setPage(-1)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($week)
            {
                try
                {
                    $data = $this->where(['week' => $week, 'status' => 1, 'user_type' => 1])->whereTime('create_time', 'today')->column('zan', 'id');
                    $resData = [];
                    foreach ($data as $id => $zanNum)
                    {
                        $resData[$id] = ['zan' => $zanNum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'zan', 0, 'today');

        return $rankingPageData['data'] ? array_keys($rankingPageData['data']) : [];
    }

    /**
     * 获取用户 参与海报活动ID
     * @param $uid
     * @param $page
     * @return array|mixed
     * @throws \Exception
     */
    public function getUserJoinPosterIds($uid, $page)
    {
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('user_join_record', $uid)
            ->setPage($page)
            ->setPageSize(10)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($uid)
            {
                try
                {
                    $data = $this->where(['uid' => $uid, 'status' => 1])->order('id ' . $sortType)->column('create_time', 'id');
                    $resData = [];
                    foreach ($data as $id => $zanNum)
                    {
                        $resData[$id] = ['create_time' => $zanNum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'create_time', 0, 'user_join_record');

        return $rankingPageData;
    }

    /**
     * 获取本周所有上传海报IDS
     * @param $week
     * @return array
     * @throws \Exception
     */
    public function getWeekAllPosterIds($week)
    {
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel, $week)
            ->setPage(-1)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($week)
            {
                try
                {
                    $data = $this->where(['week' => $week, 'status' => 1])->column('zan', 'id');
                    $resData = [];
                    foreach ($data as $id => $zanNum)
                    {
                        $resData[$id] = ['zan' => $zanNum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'zan', 0, 'list');

        return $rankingPageData['data'] ? array_keys($rankingPageData['data']) : [];
    }

    /**
     * 获取用户已读所有海报ids
     * @param $uid
     * @return array
     * @throws \Exception
     */
    public function getUserReadPosterIds($uid)
    {
        $rankingPageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('user_read', $uid)
            ->setPage(-1)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($uid)
            {
                return [];
            }, 'create_time', 0, 'user_read');

        return $rankingPageData['data'] ? array_keys($rankingPageData['data']) : [];
    }

    /**
     * 看过添加
     * @param $uid
     * @param $posterId
     * @throws \Exception
     */
    public function userReadPOsterIdAdd($uid, $posterId)
    {
        CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('user_read', $uid)
            ->listAdd([$posterId => time()], 0, 'user_read');
    }

    /**
     * 获取投票列表
     * @param $week
     * @param $uid
     * @param $limit
     * @return array
     * @throws \Exception
     */
    public function getLists($week, $uid, $limit)
    {
        $day = $week . ':' . date('Ymd');
        // 获取用户已读所有ids
        $userReadIds = $this->getUserReadPosterIds($uid);
        // 获取用户自己当前海报id
        $nowPosterId = $this->getNowWeekPosterId($uid, $week);
        // 获取虚拟海报ids
        $virtualPosterIds = $this->getVirtualPosterIds($week);
        // 获取当日上传ids
        $todayPosterIds = $this->getTodayPosterIds($week, $day);
        // 获取 本周期内 所有海报ids
        $allPosterIds = $this->getWeekAllPosterIds($week);

        $resIds = $this->getListIds($userReadIds, $nowPosterId, $virtualPosterIds, $todayPosterIds, $allPosterIds);
        if (empty($resIds) && !empty($userReadIds))
        {   // 如果所有的都看过了  则 删除看过了的缓存
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('user_read', $uid)->rmCache('user_read');
        }
        if (count($resIds) < $limit)
        {
            $resIds2 = $this->getListIds($resIds, $nowPosterId, $virtualPosterIds, $todayPosterIds, $allPosterIds);
            foreach ($resIds2 as $posterId)
            {
                $resIds[] = $posterId;
            }
        }

        // 获取点赞的用户ID
        $zanIds = (new ZlPosterShareActiveZanRecord())->getZanPosterIds($uid);
        $resData = [];
        foreach ($resIds as $posterId)
        {
            $posterInfo = $this->getInfoById($posterId);

            if ($posterInfo && (int)$posterInfo['status'] === 1)
            {
                $resData[] = [
                    'id' => (int)$posterId,
                    'poster_url' => $posterInfo['poster'],
                    'nickname' => $posterInfo['nickname'],
                    'avatar' => $posterInfo['avatar'],
                    'zan_num' => $posterInfo['zan'],
                    'is_zan' => isset($zanIds[$posterId]) ? 1 : 0,
                ];

                $limit--;
                if ($limit <= 0)
                {
                    break;
                }
            }
        }

        return $resData;
    }

    /**
     * 获取列表ID
     * @param array $notInIds
     * @param int $nowPosterId
     * @param array $virtualPosterIds
     * @param array $todayPosterIds
     * @param array $allPosterIds
     * @return array
     */
    private function getListIds(array $notInIds, int $nowPosterId, array $virtualPosterIds, array $todayPosterIds, array $allPosterIds)
    {
        $resIds = [];

        if (!in_array($nowPosterId, $notInIds, false))
        {
            $resIds[] = $nowPosterId;
        }

        $virtualRes = array_diff($virtualPosterIds, $notInIds);
        if ($virtualRes)
        {
            if (count($virtualRes) > 5)
            {
                $virtualRes = array_rand($virtualRes, 5);
            } else
            {
                shuffle($virtualRes);
            }
            foreach ($virtualRes as $posterId)
            {
                $resIds[] = $posterId;
            }
        }

        $todayResIds = array_diff($todayPosterIds, $notInIds);
        if ($todayResIds)
        {
            if (count($todayResIds) > 5)
            {
                $todayResIds = array_rand($todayResIds, 5);
            } else
            {
                shuffle($todayResIds);
            }

            foreach ($todayResIds as $posterId)
            {
                $resIds[] = $posterId;
            }
        }

        $allResIds = array_diff($allPosterIds, $notInIds, $resIds);
        if ($allResIds)
        {
            shuffle($allResIds);
            foreach ($allResIds as $posterId)
            {
                $resIds[] = $posterId;
            }
        }

        return $resIds;
    }

    /**
     * 是否参与本期评选
     * @param $uid
     * @param int $weekNum 周期
     * @return int     1=>已参与。 0=>未参与  2=>违规本期禁止参与
     * @throws \Exception
     */
    public function isJoin($uid, int $weekNum)
    {
        $posterId = $this->getNowWeekPosterId($uid, $weekNum);

        $status = $posterId ? 1 : 0;
        if ($posterId)
        {
            $posterInfo = $this->getInfoById($posterId, ['status']);
            if ($posterInfo && isset($posterInfo['status']) && (int)$posterInfo['status'] === 2)
            {
                $status = 2;
            }
        }

        return $status;
    }
}
